#!/usr/bin/env python3.6
# encoding: utf-8
import multiprocessing

import cv2 as cv
import os
from uitils.sqlhelper import fetchall
from uitils.yolov5_trt import YoLov5TRT
from uitils.yolov_utils import img_pro, get_coordinates, if_inPoly
import pycuda.autoinit
import datetime
import numpy as np
import shutil
from pathlib import Path
from flask import Flask,request,send_file


file_yaml = 'config/coco.yaml'
multipros = []    # 进程列表
lock = None       # 进程锁
sep = os.sep
# 先定义本地存储图片和视频的路径
current_date = datetime.datetime.now().strftime("%Y-%m-%d")

file_dir_local = os.getcwd()
data_dir = file_dir_local+sep+'data'+sep+'uploads'+sep+current_date+sep

FILE = Path(__file__).resolve()
ROOT = FILE.parents[0]


#加载日志配置文件
import logging.config

logging.config.fileConfig('logs/log.conf')
aa = logging.getLogger('root')

categories = ["person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
              "traffic light",
              "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
              "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
              "frisbee",
              "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard",
              "surfboard",
              "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
              "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
              "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard",
              "cell phone",
              "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
              "teddy bear",
              "hair drier", "toothbrush"]



app = Flask(__name__)

def visualize(result_boxes, result_scores, result_classid,img,sx_ip, class_name,conf, lock,pim):    #img,sx_ip, bbox_array, class_name,conf,lock,pim
    """
    ,img,pim,class_name,sx_ip,conf
    a 为识别结果的坐标
    b 为设别结果的执行度
    c 为识别结果的类别

    """
    conf_list = conf.split(',')
    primes = [int(i) for i in class_name]
    for j in range(len(result_boxes)):
        clas = int(result_classid[j].tolist())
        score = result_scores[j].tolist()
        temp = result_boxes[j].tolist()

        clas_type = type(clas)
        score_type = type(score)
        zuobiao_type = type(temp)
        square = [(540, 577), (376, 655), (822, 792), (1404, 729), (1022, 611)]
        pts = np.array(square, np.int32)
        if pim == 'Y':
            cv.polylines(img, [pts], True, (255, 0, 0), 2)
            if clas in primes:
                square_class = [(int(temp[0]), int(temp[1])), (int(temp[0]), (int(temp[0] + temp[2]))),
                                (int(temp[0] + temp[2]), int(temp[1] + temp[3])),
                                (int(temp[0]) + temp[3], int(temp[1]))]
                # xywh
                ret = get_coordinates(square_class)

                is_true = if_inPoly(square, ret[0])
                if is_true:
                    cv.rectangle(img, (int(temp[0]), int(temp[1])), (int(temp[2]), int(temp[3])),
                                  (0, 0, 255), 2)
                    if clas in [0.0, 1.0]:
                        img = cv.putText(img, "Personnel Entry", (int(temp[0]), int(temp[1]) - 10),
                                          cv.FONT_HERSHEY_SIMPLEX, 1.1, (0, 0, 255), 1)  # (105, 237, 249)
                    else:
                        img = cv.putText(img, categories[clas], (int(temp[0]), int(temp[1]) - 5),
                                          # "class:" + str(clas)
                                          cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)  # (105, 237, 249)
                    date = datetime.datetime.now().strftime("%Y-%m-%d")
                    img_pro(img, sx_ip, clas, score, date)
        else:

            if clas in primes:
                if score >= float(0.93):
                    cv.rectangle(img, (int(temp[0]), int(temp[1])), (int(temp[2]), int(temp[3])),   #, int(temp[1] + temp[2])  #(int(temp[0] + temp[3]), int(temp[1] + temp[2])
                                  (0, 0, 255), 2)
                    img = cv.putText(img, categories[clas] + " " + str(round(score, 2)),  # "class:" + str(clas)
                                      (int(temp[0]), int(temp[1]) - 10),
                                      cv.FONT_HERSHEY_SIMPLEX, 1.1, (0, 0, 255), 1)
                    # 添加时间
                    timestamp = datetime.datetime.now()
                    img = cv.putText(img, timestamp.strftime(
                        "%A %d %B %Y %I:%M:%S%p"), (20, img.shape[0] - 30),
                                      cv.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 1)
                    date = datetime.datetime.now().strftime("%Y-%m-%d")
                    # 调用处理图片策略的方法
                    img_pro(img,sx_ip,clas,score,date)
    return img, sx_ip

def detect_motion(stream_name,sx_ip, class_name,conf, lock,pim):
    count = 0
    capture = cv.VideoCapture(stream_name)
    size = (1420, 799)
    yolov5_wrapper = YoLov5TRT(file_yaml)
    while True:
        ret, frame = capture.read()
        count += 1
        if frame is None:
            print('视频中断了')
            # capture.stop()
            capture.replace()
            capture = cv.VideoCapture(stream_name)
            continue
        if ret == True and count%30==0:  #and count%5==0
            frame = cv.resize(frame, size)
            a, b, c = yolov5_wrapper.infer(frame)
            img, sx_ip =visualize(a, b, c,frame,sx_ip, class_name,conf, lock,pim)
            # cv.imshow(f"{sx_ip}", img)
def main(sql_1):
    results = fetchall(sql_1)
    multiprocessing.set_start_method("spawn")
    # ctx = multiprocessing.get_context('spawn')

    global lock
    lock = multiprocessing.RLock()
    cpu_count = multiprocessing.cpu_count()
    if len(results) <= cpu_count - 1:
        for m in range(len(results)):
            multipros.append(
                # stream_name,sx_ip, stream_img_path, class_name,sx_id,conf, lock
                multiprocessing.Process(
                    # stream_name,sx_ip, stream_img_path, class_name,conf, lock,pim
                    target=detect_motion, args=(
                    results[m][11], results[m][10], results[m][13].split(","), results[m][12], lock, results[m][18]),
                    name=results[m][10])
            )
        for bb in multipros:
            bb.start()
        for bb in multipros:
            bb.join()

"""
#启动所有摄像头推理过程
"""

@app.route('/deteset')
def cs1():
    try:
        sql_1="select * from ep_equipdata limit 2"
        # sql_1 = "select * from ep_equipdata where ip='192.168.31.64'"
        main(sql_1)
        status = 'success'
    except Exception as e:
        status = f'error {e}'
        aa.error(e)

    return status

"""
#杀死所有摄像头推理过程
"""
@app.route('/exit_deteset',methods=['GET',"POST"])
def cs2():
    try:
        for pro in multipros:
            pid = pro.pid
            # process = f'kill -9 {pid}'
            process = f'kill -9 {pid}'
            stat = os.system(process)

        multipros.clear()
        status = 'success'
    except Exception as e:
        status = f'error {e}'
        aa.error(e)

    return status


"""
#杀死指定摄像头进程
"""
@app.route('/exit',methods=['GET',"POST"])
def cs3():
    try:
        status = ''
        #win 通过pid杀死进程
        if request.method == 'POST':
            name = request.form.get('sx_ip')
            # pid  = get_pid(name)
            if len(multipros)!=0:

                for pro in multipros:
                    if name==pro.name:
                        pid = pro.pid
                        process = f'kill -9 {pid}'
                        # process = f'kill -9 {pid}'
                        stat = os.system(process)
                        if stat==0:
                            status = 'success'
                            multipros.remove(pro)
                            dir_path = data_dir+f'{name}'
                            shutil.rmtree(dir_path,ignore_errors=True)   #如果报oserror  加参数 ignore_errors=True
                        else:
                            status = 'error'

            else:
                status = 'Error 没有启动对应进程！'

    except Exception as e:
        status = f'error {e}'
        aa.error(e)

    return status



"""
#重新启动指定摄像头
"""
@app.route('/dispose',methods=['GET',"POST"])
def cs4():
    try:
        status = ''
        global lock
        lock= lock
        if request.method == 'POST':
            name = request.form.get('sx_ip')
            #先去判断一下ip是否在进程列表中
            for pro in multipros:
                if name == pro.name:
                    status="已存在，添加失败"
                else:
                    sql_2 = "select * from ep_equipdata where ip='%s'" % name

                    results = fetchall(sql_2)

                    # stream_name,sx_ip, stream_img_path, class_name,sx_id,conf, lock
            #args=(results[m][11],results[m][10],results[m][13].split(","),results[m][12], lock,results[m][18]),name=results[m][5])
            new_process = multiprocessing.Process(
                target=detect_motion, args=(
                results[0][11], results[0][10], results[0][13].split(","), results[0][12],
                lock,results[0][18]), name=results[0][10])
            new_process.start()
            multipros.append(new_process)
            # new_process.join()
            status = 'success'
    except Exception as e:
        status = f"error {e}"
        aa.error(e)
    return status

"""
删除图片文件夹，默认保存10天
"""
@app.route('/remove_folders')
def cs5():
    change_time = datetime.datetime.now() + datetime.timedelta(days=-10)

    date = change_time.strftime("%Y-%m-%d")
    upload_path = r'data\uploads'
    date_path = os.path.join(ROOT, upload_path + f'/{date}' + sep)
    try:
        if os.path.exists(date_path):
            shutil.rmtree(date_path)
            status = 'success'
    except Exception as e:
        print(e)
        status = 'Delete failed'

    return status

"""
# 下载日志文件
"""
@app.route("/download")
def download():
    try:
        down_file = os.path.join(ROOT,'logs'+sep+'root.log')
        return send_file(down_file, as_attachment=True)
    except Exception as e:
        aa.error(e)


if __name__ == "__main__":
    app.run(host='192.168.31.119', port='8880',debug=False)

